package views.components;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set;

import utils.MessageUtils;
import utils.ReflectionUtils;

import com.vaadin.addon.jpacontainer.EntityItem;
import com.vaadin.addon.jpacontainer.JPAContainer;
import com.vaadin.addon.jpacontainer.JPAContainerFactory;
import com.vaadin.addon.jpacontainer.util.HibernateLazyLoadingDelegate;
import com.vaadin.data.Property;
import com.vaadin.data.Validator;
import com.vaadin.data.Validator.InvalidValueException;
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomField;
import com.vaadin.ui.Table;
import com.vaadin.ui.VerticalLayout;

import config.Parameters;
import dao.interfaces.IBase;

@SuppressWarnings("serial")
public class SelectorOneToMany extends CustomField<Object> {

	private Class<IBase> myClass;
	private JPAContainer<IBase> jpaContainer;
	private Table table;

	public SelectorOneToMany(Class<IBase> myClass) {

		this.myClass = myClass;

		table = new Table();
		table.setSelectable(true);
		table.setMultiSelect(true);
		table.setNullSelectionAllowed(true);
		setImmediate(true);

		jpaContainer = JPAContainerFactory.make(myClass,
				Parameters.DB_DATA_SOURCE);
		jpaContainer.getEntityProvider().setLazyLoadingDelegate(
				new HibernateLazyLoadingDelegate());

		table.setContainerDataSource(jpaContainer);
		table.setPageLength(Math.min(jpaContainer.size(), 10));
		// agafe les columnes que seran visibles per esta @view en myClass

		ArrayList<String> columnes = ReflectionUtils.getViewFields(myClass,
				"selector");

		// anyadim la columna generada del comboBox
		// accio que realitzara el boto de executar
		table.setVisibleColumns(columnes.toArray());

		// creem les cabeceres de les columnes de la tabla internacionalitzades
		String[] headers = new String[columnes.size()];
		for (int i = 0; i < columnes.size(); i++)
			headers[i] = MessageUtils.getI18n(columnes.get(i));

		table.setColumnHeaders(headers);

		table.addValidator(new Validator() {

			@Override
			public void validate(Object value) throws InvalidValueException {
				if (table.getValue() != null) {
					setRequired(false);
				} else {
					setRequired(true);
				}
			}
		});

	}

	@Override
	public void validate() throws InvalidValueException {

		if (getValue() != null) {
			setRequired(false);
		} else {
			setRequired(true);
		}
	}

	@Override
	protected Component initContent() {
		VerticalLayout root = new VerticalLayout();
		setCaption(MessageUtils.getI18n(myClass.getSimpleName()));
		root.addComponent(table);
		return root;
	}

	@Override
	public Class<? extends ArrayList> getType() {
		return new ArrayList().getClass();
	}

	@Override
	public Object getValue() {
		ArrayList<Object> arrayList = new ArrayList<>();

		if (table.getValue() instanceof ArrayList<?>) {
			arrayList = (ArrayList<Object>) table.getValue();

			for (Object object : arrayList) {
				System.out.println(object.toString());
			}
		}

		if (table.getValue() instanceof Set) {
			Set set = (Set) table.getValue();
			if (set != null) {

				Iterator iterator = set.iterator();

				while (iterator.hasNext()) {
					Object object = (Object) iterator.next();
					EntityItem<IBase> item = jpaContainer.getItem(object);
					IBase entity = item.getEntity();
					arrayList.add(entity);
				}
			}
		}

		return arrayList;
	}

	@Override
	public Property<Object> getPropertyDataSource() {

		Property<Object> propertyDataSource = super.getPropertyDataSource();
		Object value = getValue();
		propertyDataSource.setValue(value);

		return propertyDataSource;
	}

	@Override
	public void setPropertyDataSource(Property newDataSource) {
		super.setPropertyDataSource(newDataSource);

		if (newDataSource != null) {
			ArrayList<IBase> value = (ArrayList<IBase>) newDataSource
					.getValue();

			setIbase(value);
		}
	}

	private void setIbase(ArrayList<IBase> list) {

		if (list == null) {
			;
		} else {
			ArrayList<Object> ids = new ArrayList<>();

			for (IBase iBase : list) {
				ids.add(iBase.getId());
			}

			table.setValue(ids);
		}

	}
}
